-- utils.lua

local modname = minetest.get_current_modname()

if not throwables then return end
local throwables = throwables

-- Initialize new throwable
function throwables:init(name, properties)
    local self = setmetatable({}, throwables)

    self.name = name
    self.properties = properties
    self.projectile_name = properties.projectile_name or name .. '_thrown'

    self.node_hit_callbacks = {}
    self.entity_hit_callbacks = {}
    self.player_hit_callbacks = {}

    return self
end

-- Register new projectile entity
function throwables:register_entity(name, properties)

    minetest.register_entity(self.projectile_name, {
        initial_properties = self.properties.initial_properties,
        glow = self.properties.glow,
        _player_name = '',

        on_step = function(_, dtime, moveresult)
            self:on_step(_, dtime, moveresult)
        end,
        on_activate = function(_, staticdata)
            self:on_activate(_, staticdata)
        end,
    })

    self.registered_entity = minetest.registered_entities[self.projectile_name]

end

-- On_use function for throwable items
function throwables:on_use(itemstack, player, pointed_thing)
    if not pointed_thing or pointed_thing.type == 'nothing' then
        self:throw(player)
    end
    return nil
end

-- Overrides an existing item to make it throwable
function throwables:override_on_use(name)
      local odef = {
          on_secondary_use = function(itemstack, player, pointed_thing)
              return self:on_use(itemstack, player, pointed_thing)
          end
      }

      if minetest.registered_items[name] then
          local old_on_use = minetest.registered_items[name].on_secondary_use
          local used
          if old_on_use then
              odef.on_secondary_use = function(itemstack, player, pointed_thing)
                  used = self:on_use(itemstack, player, pointed_thing)
                  if not uded and old_on_use then return old_on_use(itemstack, player, pointed_thing) end
              end
              return used
          end
      end

      minetest.override_item(name, odef)

      return self
  end

-- Register a new throwable item
function throwables:register_item(name, properties)

    minetest.register_craftitem(self.name, {
        description = self.properties.description,
        inventory_image = self.properties.inventory_image,
        stack_max = self.properties.stack_max,
          on_secondary_use = function(_, player, pointed_thing)
                  self:on_use(_, player, pointed_thing)
          end,
    })

    self.registered_item = minetest.registered_items[self.name]

    return self
end


-- Create the projectile entity and make it fly
function throwables:throw(player)
    local throw_starting_pos = vector.add({x=0, y=1.5, z=0}, player:get_pos())
    local thrown_obj = minetest.add_entity(throw_starting_pos, self.projectile_name, player:get_player_name())

    local item = self.name
    local wielded_item = player:get_wielded_item()
    if wielded_item:get_name() == self.name then
        item = wielded_item
        wielded_item:take_item()  -- Retire un exemplaire de l'objet tenu
        player:set_wielded_item(wielded_item)  -- Met à jour l'objet tenu
    else
        minetest.after(0, function(i) player:get_inventory():remove_item("main", i) end, item)
    end

    minetest.sound_play(modname.. "_throw", {max_hear_distance = 10, pos = player:get_pos()})
end

-- On_activate function for throwable projectile
function throwables:on_activate(_, staticdata)
    if not staticdata or not minetest.get_player_by_name(staticdata) then
        _.object:remove()
        return
    end
    _._player_name = staticdata
    local player = minetest.get_player_by_name(staticdata)
    local yaw = player:get_look_horizontal()
    local pitch = player:get_look_vertical()
    local dir = player:get_look_dir()

    _.object:set_rotation({x = -pitch, y = yaw, z = 0})
    _.object:set_velocity({
        x=(dir.x * _.initial_properties.speed),
        y=(dir.y * _.initial_properties.speed),
        z=(dir.z * _.initial_properties.speed),
    })
    _.object:set_acceleration({x=dir.x*-4, y=-_.initial_properties.gravity, z=dir.z*-4})

    minetest.after(_.initial_properties.lifetime, function() _.object:remove() end)
end

-- On_step function, handle collisions for throwable projectile
function throwables:on_step(_, dtime, moveresult)
    local collided_with_node = moveresult.collisions[1] and moveresult.collisions[1].type == "node"
    local collided_with_entity = moveresult.collisions[1] and moveresult.collisions[1].type == "object"

    if collided_with_node then
        for i = 1, #self.node_hit_callbacks do
            local pos = moveresult.collisions[1].node_pos
            local node = minetest.get_node(pos)
            self.node_hit_callbacks[i](_, node, pos)
        end
        _.object:remove()
    elseif collided_with_entity then
        -- local entity = minetest.get_object_by_handle(moveresult.collisions[1].collided_obj)
        local obj = moveresult.collisions[1].object
        print(dump(obj))
        if obj:is_player() then
            for i = 1, #self.player_hit_callbacks do
                self.player_hit_callbacks[i](_, obj)
            end
        else
            for i = 1, #self.entity_hit_callbacks do
                self.entity_hit_callbacks[i](_, obj)
            end
        end
      _.object:remove()
    end
end


